<?php
// 应用公共文件
use app\common\model\ConsultingMessage;
use ShidianUtil\Utils\ArrayUtil;
use ShidianUtil\Utils\CheckUtil;
use ShidianUtil\Utils\RandUtil;
use ShidianUtil\Utils\StringUtil;
use ShidianUtil\Utils\TimeUtil;
use think\Collection;
use think\db\Query;
use think\exception\ValidateException;
use think\facade\Config;
use think\facade\Request;
use think\helper\Str;
use think\Model;

/**
 * 是不是ID
 * @param $id
 * @return bool
 */
function is_id($id): bool
{
    return is_numeric($id) && $id > 0;
}

/**
 * 字符串是否为空
 * @param string|null $string
 * @return bool
 */
function not_blank(?string $string): bool
{
    return StringUtil::notBlank($string);
}

/**
 * 字符串是否非空
 * @param string|null $string
 * @return bool
 */
function is_blank(?string $string): bool
{
    return StringUtil::isBlank($string);
}

/**
 * 补全图片链接域名
 * @param string|null $path
 * @param string $process 图片处理
 * @return string
 */
function image_url(?string $path, string $process = ''): string
{
    $path = trim($path);

    if (not_blank($path) && !CheckUtil::isUrl($path)) {
        // 兼容旧数据
        if (!StringUtil::startsWith($path, '/storage')) {
            $path = '/storage' . $path;
        }

        if (is_development()) {
            $hosts = 'http://xiongmaolvshiadmin.api.local';
        } elseif (is_test()) {
            $hosts = 'https://tapi.xiongmaolvshi.cn';
        } else {
            $hosts = 'https://staticcdn.xiongmaolvshi.cn';
        }

        $path = $hosts . $path;

        // 图片处理
        if (not_blank($process)) {
            $path .= Config::get('fileprocess.delimiter', '-') . $process;
        }
    }

    return $path;
}

/**
 * 输出列表
 * @param Query|Model $query
 * @param int $page_size
 * @return array
 */
function listOutput($query, int $page_size): array
{
    if ($page_size <= 0) {
        $page_size = 1;
    }

    $count = $query->count();

    return [
        'list' => $query->select(),
        'total' => $count,
        'total_page' => ceil($count / $page_size)
    ];
}

/**
 * 指定长度uuid
 * @param int $length
 * @return string
 */
function uuid(int $length = 20)
{
    return RandUtil::uuid($length);
}

/**
 * 对象合并
 * @param $object
 * @param $object0
 * @return stdClass
 */
function object_merge($object, $object0)
{
    return (object)array_merge((array)$object, (array)$object0);
}

/**
 * 人性化可读的时长
 * @param $time_length
 * @return string
 */
function humanized_time_length($time_length): string
{
    $str = '';
    if ($time_length > 86400) {
        $str .= floor($time_length / 86400) . '天';
        $time_length = $time_length % 86400;
    }

    if ($time_length > 3600) {
        $str .= floor($time_length / 3600) . '小时';
        $time_length = $time_length % 3600;
    }

    if ($time_length >= 60) {
        $str .= floor($time_length / 60) . '分钟';
    }

    return $str;
}

function humanized_time($time): string
{
    $time_length = time() - $time;

    if ($time_length >= 86400) {
        return floor($time_length / 86400) . '天前';
    }

    if ($time_length >= 3600) {
        return floor($time_length / 3600) . '小时前';
    }

    if ($time_length >= 60) {
        return floor($time_length / 60) . '分钟前';
    }

    return '刚刚';
}

/**
 * 集合字段收集
 * @param Collection $collection
 * @param string $field
 * @return Collection
 */
function collection_field_collect(Collection $collection, string $field): Collection
{
    $result = \think\model\Collection::make();
    $collection->each(function ($item) use (&$result, $field) {
        if ($item->$field instanceof Collection) {
            $result = $result->merge($item->$field);
        } elseif (!is_null($item->$field)) {
            $result->push($item->$field);
        }
    });
    return $result;
}

/**
 * 数组，集合 匹配
 * @param $key
 * @param Closure $closure
 * @param array|Collection ...$arrays
 * @return void
 */
function collection_match($key, Closure $closure, ...$arrays): void
{
    $keys = [];
    foreach ($arrays as $k => $array) {
        if (is_array($array)) {
            $arrays[$k] = array_column($array, null, $key);
        } elseif ($array instanceof Collection) {
            $arrays[$k] = $array->column(null, $key);
        } else {
            throw new RuntimeException('只支持数组');
        }
        $temp_keys = array_keys($arrays[$k]);
        if (!empty($temp_keys)) {
            $keys = array_merge($keys, $temp_keys);
        }
    }

    foreach ($keys as $key) {
        $args = [];
        foreach ($arrays as $array) {
            $args[] = $array[$key] ?? null;
        }
        $closure(...$args);
    }
}

/**
 * 随机获取集合元素
 * @param Collection $collection
 * @return mixed|null
 */
function collection_rand(Collection $collection)
{
    if ($collection->isEmpty()) {
        return null;
    }

    $count = $collection->count();

    if ($count == 1) {
        return $collection[0];
    }

    return $collection[mt_rand(0, $count - 1)];
}

/**
 * 按类型实例化类
 * @param $interface
 * @param $type
 * @param string $prefix
 * @param string $suffix
 */
function app_instance($interface, $type, string $prefix = '', string $suffix = 'Service')
{
    // 如果传的类名称，直接实例化
    if (class_exists($type)) {
        return app($type);
    }

    // 查询配置中是否存在
    $config = \think\facade\Config::get('appprovider.' . $interface, []);
    if (!empty($config) && isset($config[$type])) {

        $class_name = $config[$type];
    } else {

        // 查询接口同目录下是否存在
        $interface_arr = explode('\\', $interface);
        array_pop($interface_arr);
        $interface_arr[] = $prefix . Str::studly($type) . $suffix;
        $class_name = implode('\\', $interface_arr);
    }

    if (is_null($class_name) || !class_exists($class_name)) {
        return null;
    }

    return app($class_name);
}

/**
 * 参数收集，只要非null参数
 * @param array $params
 * @param array $map
 * @return array
 */
function collect_params(array $params, array $map): array
{
    $result = [];
    foreach ($map as $key => $value) {
        if (isset($params[$value])) {
            if (is_numeric($key)) {
                $result[$value] = $params[$value];
            } else {
                $result[$key] = $params[$value];
            }
        }
    }
    return $result;
}

/**
 * 获取数组的ID
 * @param array $array
 * @param string $column
 * @return array
 */
function ids(array $array, string $column = 'id'): array
{
    return ArrayUtil::ids($array, $column);
}

/**
 * 显示金额，强制两位小数
 * @param $money
 * @param int $decimals
 * @return string
 */
function money_show($money, int $decimals = 2): string
{
    return number_format($money, $decimals, '.', '');
}

/**
 * 账户类型（支付方式类型）
 * @param $accountType
 * @param string $type
 * @return string
 */
function account_type_str($accountType, string $type = 'pay'): ?string
{
    if ($type == 'transfer') {
        // 转账
        $accountTypeStr = Config::get("payment.transfers.$accountType.name", null);
        if (is_null($accountTypeStr)) {
            $accountTypeStr = Config::get("payment.transfersbatch.$accountType.name", null);
        }
        return $accountTypeStr;
    } else {
        // 支付和退款
        return Config::get("payment.payments.$accountType.name", null);
    }

}

/**
 * 设置数组参数中的字段值在范围内
 * @param array $params
 * @param string $key
 * @param $first
 * @param $second
 * @param ...$enums
 * @return void
 */
function params_enums(array &$params, string $key, $first, $second, ...$enums): void
{
    if (!isset($params[$key])) {
        return;
    }

    array_unshift($enums, $first, $second);

    if (!in_array($params[$key], $enums)) {
        $params[$key] = $first;
    }
}

function messageContentStr($messageType, $content): string
{
    if ($messageType == ConsultingMessage::TEXT) {
        return $content['text'] ?? '';
    }
    if ($messageType == ConsultingMessage::IMAGE) {
        return '[图片]';
    }
    if ($messageType == ConsultingMessage::SERVER) {
        return '[咨询服务]';
    }
    if ($messageType == ConsultingMessage::LAWYER) {
        return '[律师名片]';
    }
    if ($messageType == ConsultingMessage::SYSTEM) {
        return implode('', array_column($content['templates'], 'text'));
    }
    if ($messageType == ConsultingMessage::COMMENT) {
        return '[评价]';
    }
    if ($messageType == ConsultingMessage::REWARD) {
        return '[悬赏]';
    }
    if ($messageType == ConsultingMessage::REDPACKET) {
        return '[红包]';
    }
    if ($messageType == ConsultingMessage::PHONE) {
        return '[联系电话]';
    }

    return '[消息]';
}


/**
 * 判断用户是否被封禁
 * @param $status
 * @return void
 */
function check_member_status($status): void
{
    if ($status == 1) {
        return;
    }

    if ($status == 0) {
        throw new ValidateException('由于您的违规操作，您的账号已被封禁');
    }

    if ($status == 2) {
        throw new ValidateException('该账号已被合并，请重新登录');
    }

    throw new ValidateException('账号状态异常，请联系管理员');
}

/**
 * 显示百分比（不带符号）
 * eg:12.34
 * @param $a
 * @param $b
 * @param int $precision
 * @param string $default
 * @return string
 */
function show_float($a, $b, int $precision = 2, string $default = ''): string
{
    if (!is_numeric($a) || !is_numeric($b) || $b == 0) {
        return $default;
    }

    return round($a / $b, $precision) . '';
}

/**
 * 显示百分比分数
 * eg:12.34%
 * @param $a
 * @param $b
 * @param int $precision
 * @param string $default
 * @return string
 */
function show_percentage($a, $b, int $precision = 2, string $default = '0%'): string
{
    if (!is_numeric($a) || !is_numeric($b) || $b == 0) {
        return $default;
    }

    return round($a / $b * 100, $precision) . '%';
}

/**
 * 小数格式化
 * @param $number
 * @param $decimals
 * @param $dec_point
 * @param $thousands_sep
 * @return string
 */
function float_format($number, $decimals = 0, $dec_point = '.', $thousands_sep = ''): string
{
    return number_format($number, $decimals, $dec_point, $thousands_sep);
}

/**
 * 获取 渠道链路参数
 * @return array
 */
function getChainParams(): array
{
    $pf = Request::header('pf', '');
    $chain = Request::header('chain', '');
    $promotionGroupId = Request::header('gid', '0');
    if (!is_id($promotionGroupId)) {
        $promotionGroupId = '0';
    }

    return [
        'pf' => $pf,
        'chain' => $chain,
        'promotionGroupId' => $promotionGroupId,
    ];
}

/**
 * 当前是否是本地开发环境
 * @return bool
 */
function is_development(): bool
{
    return env('PROFILE') === 'develop';
}

/**
 * 当前是否是线上测试环境
 * @return bool
 */
function is_test(): bool
{
    return env('PROFILE') === 'test';
}

/**
 * 当前是否是线上生产环境
 * @return bool
 */
function is_production(): bool
{
    return env('PROFILE') === 'production';
}

/**
 * 获取类名称，不包含名称空间
 * @param $object
 * @return string
 */
function get_class_name($object): string
{
    $class = get_class($object);

    $class = explode('\\', $class);

    return array_pop($class);
}

/**
 * 补齐集合数据
 * @param array $array
 * @param array $map
 * @param callable $callback
 * @return array
 */
function array_completion(array $array, array $map, callable $callback): array
{

    $result = [];
    foreach ($map as $key => $values) {
        foreach ($values as $value) {
            $current = ArrayUtil::find($array, fn($item) => StringUtil::equals($item[$key], $value));
            if (!$current) {
                $current = $callback($key, $value);
            }
            $result[] = $current;
        }
    }
    return $result;
}

// *************************** 业务逻辑 ***************************

/**
 * 是否填写了补充信息
 * @param $details
 * @return int
 */
function details_valid($details): int
{
    if (!is_array($details)) {
        return 0;
    }

    foreach ($details as $detail) {
        $result = $detail['result'] ?? null;
        if (not_blank($result)) {
            return 1;
        }
    }

    return 0;
}

/**
 * 转换熊猫分页参数为案如云分页参数
 * @param $params
 * @return void
 */
function ary_page(&$params)
{
    if (!isset($params['page_size'])) {
        return;
    }
    $params['pagesize'] = $params['page_size'];
    unset($params['page_size']);
}

/**
 * 是否属于夜间服务时间(0:00 ~8:00)
 * @param $time
 * @return bool
 */
function at_night($time): bool
{
    $startTime = TimeUtil::stamp(TimeUtil::DAY, $time);
    $endTime = $startTime + 9 * 3600;
    return $time >= $startTime && $time < $endTime;
}

/**
 * 克隆集合
 * @param Collection $collection
 * @return Collection
 */
function clone_collection(Collection $collection): Collection
{
    $collection = clone $collection;

    return $collection->map(function ($item) {
        if ($item instanceof Collection) {
            $item = clone_collection($item);
        } elseif ($item instanceof Model) {
            $item = clone_model($item);
        } else {
            $item = clone $item;
        }
        return $item;
    });
}

/**
 * 克隆模型对象
 * @param Model $model
 * @return Model
 */
function clone_model(Model $model): Model
{
    $model = clone $model;

    foreach ($model->getRelation() as $k => $item) {
        if ($item instanceof Collection) {
            $item = clone_collection($item);
        } elseif ($item instanceof Model) {
            $item = clone_model($item);
        } else {
            $item = clone $item;
        }
        $model->setRelation($k, $item);
    }

    return $model;
}